home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / pmake / customs / avail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-15  |  10.0 KB  |  355 lines

  1. /*-
  2.  * avail.c --
  3.  *    Functions to check the status of the local machine to see
  4.  *    if it can accept processes.
  5.  *
  6.  * Copyright (c) 1988, 1989 by the Regents of the University of California
  7.  * Copyright (c) 1988, 1989 by Adam de Boor
  8.  * Copyright (c) 1989 by Berkeley Softworks
  9.  *
  10.  * Permission to use, copy, modify, and distribute this
  11.  * software and its documentation for any non-commercial purpose
  12.  * and without fee is hereby granted, provided that the above copyright
  13.  * notice appears in all copies.  The University of California,
  14.  * Berkeley Softworks and Adam de Boor make no representations about
  15.  * the suitability of this software for any purpose.  It is provided
  16.  * "as is" without express or implied warranty.
  17.  */
  18. #ifndef lint
  19. static char *rcsid =
  20. "$Id: avail.c,v 1.20 89/11/14 13:45:53 adam Exp $ SPRITE (Berkeley)";
  21. #endif lint
  22.  
  23. #include    "customsInt.h"
  24. #include    <stdio.h>
  25.  
  26. static unsigned long       maxLoad = 0.5 * LOADSCALE;
  27. static int            minSwapFree=25;    /* 75% used swap => not available */
  28. static int            minIdle=15*60;    /* Keyboard must have been idle at
  29.                      * least 15 minutes (when this is
  30.                      * 15 * 60)... */
  31. static int            maxImports = 2;    /* Largest number of imported jobs */
  32.  
  33. static Rpc_Event      availEvent;    /* Event for checking availability */
  34. static struct timeval    availInterval;    /* Interval at which checks should
  35.                      * be made for the availability of
  36.                      * this host. */
  37. static int              availCheck;      /* Mask of criteria to examine */
  38. int                    avail_Bias;     /* Bias for rating calculation */
  39.  
  40. /*-
  41.  *-----------------------------------------------------------------------
  42.  * Avail_Send --
  43.  *    Send the availability of the local host.
  44.  *
  45.  * Results:
  46.  *    None.
  47.  *
  48.  * Side Effects:
  49.  *    An availability packet is sent to the master.
  50.  *
  51.  *-----------------------------------------------------------------------
  52.  */
  53. Boolean
  54. Avail_Send ()
  55. {
  56.     Avail         avail;
  57.     static int      sending = 0;        /* XXX: A kludge to prevent endless
  58.                      * recursion. At times, for no reason I've
  59.                      * been able to determine, the avail event
  60.                      * will be triggered during the call to
  61.                      * CUSTOMS_AVAIL (hard to believe since
  62.                      * the timeout for the avail event is
  63.                      * twice as long as the total for the
  64.                      * rpc, but...). Once it starts, it
  65.                      * continues and the calls never seem to
  66.                      * complete. To prevent this, we use a
  67.                      * static flag and don't send anything
  68.                      * if a call is already being sent. */
  69.     if (sending) {
  70.     return(FALSE);
  71.     } else {
  72.     sending = 1;
  73.     }
  74.     
  75.     avail.addr =      localAddr.sin_addr;
  76.     avail.interval =     availInterval;
  77.     avail.avail =     Avail_Local(AVAIL_EVERYTHING, &avail.rating);
  78.  
  79.     if (verbose) {
  80.     printf ("Localhost %s available\n", avail.avail ? "not" : "is");
  81.     fflush(stdout);
  82.     }
  83.  
  84.     if (!Elect_InProgress() &&
  85.     (Rpc_Call(udpSocket, &masterAddr, (Rpc_Proc)CUSTOMS_AVAIL,
  86.           sizeof(avail), (Rpc_Opaque)&avail,
  87.           0, (Rpc_Opaque)0,
  88.           CUSTOMSINT_NRETRY, &retryTimeOut) != RPC_SUCCESS)) {
  89.               Elect_GetMaster();
  90.     }
  91.     sending = 0;
  92.     return (FALSE);
  93. }
  94.  
  95. /*-
  96.  *-----------------------------------------------------------------------
  97.  * AvailSet --
  98.  *    Set the availability criteria. Returns an OR of bits if the
  99.  *    parameters are out-of-range.
  100.  *
  101.  * Results:
  102.  *    Any of AVAIL_IDLE, AVAIL_SWAP, AVAIL_LOAD and AVAIL_IMPORTS
  103.  *    or'ed together (or 0 if things are ok).
  104.  *
  105.  * Side Effects:
  106.  *    The availabilty criteria are altered.
  107.  *
  108.  *-----------------------------------------------------------------------
  109.  */
  110. /*ARGSUSED*/
  111. static void
  112. AvailSet (from, msg, len, adPtr, fromRemote)
  113.     struct sockaddr_in    *from;        /* Address of sender */
  114.     Rpc_Message          msg;        /* Message for return */
  115.     int                  len;        /* Length of criteria */
  116.     Avail_Data          *adPtr;        /* New criteria */
  117.     Boolean           fromRemote; /* TRUE if from remote call */
  118. {
  119.     int              result;
  120.  
  121.     if (!Local(from)) {
  122.     Rpc_Error(msg, RPC_ACCESS);
  123.     } else if (len != sizeof(Avail_Data)) {
  124.     Rpc_Error(msg, RPC_BADARGS);
  125.     } else {
  126.     /*
  127.      * Bounds-check the passed parameters, setting bits in result to
  128.      * correspond to bad values.
  129.      */
  130.     result = 0;
  131.     if ((adPtr->changeMask & AVAIL_IDLE) && (adPtr->idleTime > MAX_IDLE)) {
  132.         result |= AVAIL_IDLE;
  133.     }
  134.     if ((adPtr->changeMask & AVAIL_SWAP) && (adPtr->swapPct > MAX_SWAP)) {
  135.         result |= AVAIL_SWAP;
  136.     }
  137.     if ((adPtr->changeMask & AVAIL_LOAD) &&
  138.         (adPtr->loadAvg < MIN_LOAD) &&
  139.         (adPtr->loadAvg != 0))
  140.     {
  141.         result |= AVAIL_LOAD;
  142.     }
  143.     if ((adPtr->changeMask & AVAIL_IMPORTS) &&
  144.         (adPtr->imports < MIN_IMPORTS) &&
  145.         (adPtr->imports != 0))
  146.     {
  147.         result |= AVAIL_IMPORTS;
  148.     }
  149.     if (result == 0) {
  150.         /*
  151.          * Everything ok -- change what needs changing.
  152.          */
  153.         if (adPtr->changeMask & AVAIL_IDLE) {
  154.         minIdle = adPtr->idleTime;
  155.         }
  156.         if (adPtr->changeMask & AVAIL_SWAP) {
  157.         minSwapFree = adPtr->swapPct;
  158.         }
  159.         if (adPtr->changeMask & AVAIL_LOAD) {
  160.         maxLoad = adPtr->loadAvg;
  161.         }
  162.         if (adPtr->changeMask & AVAIL_IMPORTS) {
  163.         maxImports = adPtr->imports;
  164.         }
  165.     }
  166.     /*
  167.      * Set return value: changeMask gets error bits. the other fields get
  168.      * the current criteria.
  169.      */
  170.     adPtr->changeMask = result;
  171.     adPtr->idleTime = minIdle;
  172.     adPtr->swapPct = minSwapFree;
  173.     adPtr->loadAvg = maxLoad;
  174.     adPtr->imports = maxImports;
  175.  
  176.     /*
  177.      * Only send a reply if the call was actually remote (it's not
  178.      * when called from main...)
  179.      */
  180.     if (fromRemote) {
  181.         Rpc_Return(msg, len, (Rpc_Opaque)adPtr);
  182.     }
  183.     }
  184. }
  185.  
  186. /*-
  187.  *-----------------------------------------------------------------------
  188.  * AvailSetInterval --
  189.  *    Alter the interval at which availability checks are made.
  190.  *
  191.  * Results:
  192.  *    None.
  193.  *
  194.  * Side Effects:
  195.  *    The interval in availInterval is changed and availEvent is altered
  196.  *    to reflect this change.
  197.  *
  198.  *-----------------------------------------------------------------------
  199.  */
  200. static void
  201. AvailSetInterval (from, msg, len, intervalPtr)
  202.     struct sockaddr_in    *from;
  203.     Rpc_Message          msg;
  204.     int                  len;
  205.     struct timeval    *intervalPtr;
  206. {
  207.     if (!Local(from)) {
  208.     Rpc_Error(msg, RPC_ACCESS);
  209.     } else if (len != sizeof(struct timeval)) {
  210.     Rpc_Error(msg, RPC_BADARGS);
  211.     } else if (intervalPtr->tv_sec < 5) {
  212.     Rpc_Error(msg, RPC_BADARGS);
  213.     } else {
  214.     availInterval = *intervalPtr;
  215.     Rpc_EventReset(availEvent, &availInterval);
  216.     Rpc_Return(msg, 0, (Rpc_Opaque)0);
  217.     }
  218. }
  219.  
  220. /*-
  221.  *-----------------------------------------------------------------------
  222.  * Avail_Init --
  223.  *    Initialize things for here...
  224.  *
  225.  * Results:
  226.  *    None.
  227.  *
  228.  * Side Effects:
  229.  *    We exit if can't initialize.
  230.  *
  231.  *-----------------------------------------------------------------------
  232.  */
  233. void
  234. Avail_Init(criteria, checkTime)
  235.     Avail_Data      *criteria;        /* Initial criteria */
  236.     int              checkTime;        /* Initial check interval */
  237. {
  238.     availInterval.tv_sec = checkTime ? checkTime : 10;
  239.     availInterval.tv_usec = 0;
  240.  
  241.     availCheck = OS_Init();
  242.     
  243.     availEvent = Rpc_EventCreate(&availInterval, Avail_Send, (Rpc_Opaque)0);
  244.     
  245.     Rpc_ServerCreate(udpSocket, CUSTOMS_AVAILINTV, AvailSetInterval,
  246.              Swap_Timeval, Rpc_SwapNull, (Rpc_Opaque)0);
  247.     Rpc_ServerCreate(udpSocket, CUSTOMS_SETAVAIL, AvailSet,
  248.              Swap_Avail, Swap_Avail, (Rpc_Opaque)TRUE);
  249.     
  250.     AvailSet(&localAddr, (Rpc_Message)0, sizeof(Avail_Data), criteria,
  251.          FALSE);
  252. }
  253.  
  254. /*-
  255.  *-----------------------------------------------------------------------
  256.  * Avail_Local --
  257.  *    See if the local host is available for migration
  258.  *
  259.  * Results:
  260.  *    0 if it is, else one of the AVAIL bits indicating which criterion
  261.  *    wasn't satisfied.
  262.  *
  263.  * Side Effects:
  264.  *    None.
  265.  *
  266.  *-----------------------------------------------------------------------
  267.  */
  268. int
  269. Avail_Local(what, ratingPtr)
  270.     int        what;     /* Mask of things to check */
  271.     long    *ratingPtr;    /* Place to store rating of current availabilty */
  272. {
  273.     /*
  274.      * Mask out bits the OS module says it can't check.
  275.      */
  276.     what &= availCheck;
  277.     /*
  278.      * Start the rating out with the bias factor. The bias is intended for
  279.      * situations where certains machines are noticeably faster than others
  280.      * and are to be prefered even if the two appear to be loaded the same.
  281.      */
  282.     *ratingPtr = avail_Bias;
  283.     
  284.     /*
  285.      * If an minimum idle time was specified, check to make sure the
  286.      * keyboard idle time exceeds that.
  287.      */
  288.     if ((what & AVAIL_IDLE) && minIdle) {
  289.     int idleTime = OS_Idle();
  290.  
  291.     if (idleTime < minIdle) {
  292.         if (verbose) {
  293.         printf ("Only %d seconds idle (%d min)\n",
  294.             idleTime, minIdle);
  295.         fflush(stdout);
  296.         }
  297.         return AVAIL_IDLE;
  298.     }
  299.     *ratingPtr += idleTime - minIdle;
  300.     }
  301.  
  302.     /*
  303.      * Either the machine has been idle long enough or the user didn't
  304.      * specify an idle time, so now, if the user gave a free swap space
  305.      * percentage beyond which the daemon may not go, tally up the total
  306.      * free blocks in the swap map and see if it's too few.
  307.      */
  308.     if ((what & AVAIL_SWAP) && minSwapFree) {
  309.     int swapPct = OS_Swap();
  310.     
  311.     if (swapPct < minSwapFree) {
  312.         if (verbose) {
  313.         printf ("Only %d%% free swap blocks\n", swapPct);
  314.         fflush(stdout);
  315.         }
  316.         return AVAIL_SWAP;
  317.     }
  318.     *ratingPtr += swapPct - minSwapFree;
  319.     }
  320.  
  321.     /*
  322.      * So far so good. Now if the user gave some maximum load average (note
  323.      * that it can't be 0) which the daemon may not exceed, check all three
  324.      * load averages to make sure that none exceeds the limit.
  325.      */
  326.     if ((what & AVAIL_LOAD) && maxLoad > 0) {
  327.     unsigned long    load = OS_Load();
  328.  
  329.     if (load > maxLoad) {
  330.         if (verbose) {
  331.         printf ("load: %f\n", (double) load/FSCALE);
  332.         }
  333.         return AVAIL_LOAD;
  334.     }
  335.     *ratingPtr += maxLoad - load;
  336.     }
  337.  
  338.     /*
  339.      * Reduce the rating proportional to the amount of work we've accepted if
  340.      * we're not completely full. We weight this heavily in an attempt
  341.      * to avoid double allocations by the master (by changing the rating
  342.      * drastically, we hope to shift the focus to some other available machine)
  343.      */
  344.     if ((what & AVAIL_IMPORTS) && maxImports && (Import_NJobs() >= maxImports))
  345.     {
  346.     return AVAIL_IMPORTS;
  347.     }
  348.     *ratingPtr -= Import_NJobs() * 200;
  349.  
  350.     /*
  351.      * Great! This machine is available.
  352.      */
  353.     return 0;
  354. }
  355.